#include <asm.h>
#include <vga.h>
#include <memory.h>

#define CONSOLE_TAB		4


static volatile uint16_t *vga_buf;
static uint16_t cursor_pos;


void 
vga_putc(uint16_t c){
	
	uint8_t cursor_y = cursor_pos / VGA_COLS;
	
	// If there are no attributes present use default, white on black
	if( !(c & 0xFF00) ){
		c |= (VGA_WHITE << 8) | (VGA_BLACK << 12);
	}
	
	switch( (c & 0xFF) ){
		case '\n':
			cursor_pos = (cursor_y + 1) * VGA_COLS;
			break;
		case '\r':
			cursor_pos = cursor_y * VGA_COLS;
			break;
		case '\t':
			cursor_pos += CONSOLE_TAB;
			break;
		default:
			if( c > ' ' ){
				vga_buf[cursor_pos++] = c;
			}
	}
	
	// Scroll one line down if the cursor is at the end
	if( cursor_pos >= VGA_SIZE ){
		// TODO memcpy in string.h
	}
	
	// Send the high bit and then the low bit of cursor framebuffer position
	outb(VGA_ADDR, VGA_CURS_HI);
	outb(VGA_DATA, (uint8_t)(cursor_pos >> 8));
	outb(VGA_ADDR, VGA_CURS_LO);
	outb(VGA_DATA, (uint8_t)cursor_pos);
	
}

void
vga_init(void){
	
	uint8_t vga_iomisc;
	
	// Set the base register so that the correct control ports will be used
	vga_iomisc = inb(VGA_IOMISC_R);
	vga_iomisc |= 0x1;
	outb(VGA_IOMISC_W, vga_iomisc);
	
	// Set the pointer to the VGA framebuffer
	vga_buf = (uint16_t *)(VGA_TEXT_BUF + KERNBASE);
	
	// Read current cursor position
	outb(VGA_ADDR, VGA_CURS_HI);
	cursor_pos = inb(VGA_DATA) << 8;
	outb(VGA_ADDR, VGA_CURS_LO);
	cursor_pos |= inb(VGA_DATA);
}